home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
C/C++ Users Group Library 1996 July
/
C-C++ Users Group Library July 1996.iso
/
vol_200
/
235_02
/
ovvbuf.c
< prev
next >
Wrap
Text File
|
1987-06-16
|
12KB
|
310 lines
/* 006 13-Dec-86 ovvbuf.c
Buffer management routines for ovview.c
Copyright (c) 1986 by Blue Sky Software. All rights reserved.
*/
#include <stdio.h>
#include <fcntl.h>
#include "ov.h"
#define MAX_VBUF 8 /* allow up to 8 in memory buffers */
#define VBUF_LEN 16*1024 /* a buffer is 16K - make a power of 2 */
typedef struct { /* define the View BUFfer DEScriptior */
int buflen;
long bufoff;
char far *bufp;
} VBUF_DES;
static int vidx; /* current VBUF descriptor in use */
static int vlast; /* last VBUF descriptor in use */
static int num_vbuf; /* highest buffer that can be alloc'd */
static VBUF_DES vbufd[MAX_VBUF]; /* the arrary of VBUF descriptors */
static long bufoff; /* offset in file of current buffer */
static unsigned int buflen; /* length of data in current buffer */
unsigned char far *bufp; /* begining of data in buffer */
unsigned char far *curp; /* current char location in buffer */
unsigned char far *endp; /* end of current buffer */
/*global*/ int ALTCALL vbuf_init(int );
/*global*/ int ALTCALL vbuf_free(void);
/*global*/ unsigned long ALTCALL vtell(void);
/*global*/ int ALTCALL vseek(int ,long );
/*global*/ int ALTCALL vnextch(int );
/*global*/ int ALTCALL vprevch(int );
static int ALTCALL pagefwd(int ,long );
static int ALTCALL pagebck(int ,long );
static int ALTCALL vswitch(int );
/*****************************************************************************
V B U F _ I N I T
*****************************************************************************/
int ALTCALL
vbuf_init(fh) /* initialize the buffer system */
int fh;
{
vlast = -1; /* set indexes, etc to force an */
num_vbuf = MAX_VBUF; /* so the initial read loads the */
pagefwd(fh,0L); /* first buffer from the file */
vswitch(0); /* make the 1st buffer active */
curp = bufp; /* at the 1st char in 1st buffer */
}
/*****************************************************************************
V B U F _ F R E E
*****************************************************************************/
int ALTCALL
vbuf_free() { /* release all memory buffers */
register int i;
register VBUF_DES *vp;
for (i = 0, vp = vbufd; i <= vlast; i++, vp++) { /* release all buffers */
free_f(vp->bufp);
vp->bufp = NULL;
}
}
/****************************************************************************
V T E L L
****************************************************************************/
unsigned long ALTCALL
vtell() { /* return file offset of current character */
return(bufoff + (curp - bufp));
}
/*****************************************************************************
V S E E K
*****************************************************************************/
int ALTCALL
vseek(fh,offset) /* seek to specified offset in file/buffers */
int fh;
long offset;
{
register int i;
long readoff, labs();
register VBUF_DES *vp;
/* "seek" is easy if offset is in current buffer - normal case I hope */
if (offset >= bufoff && offset < bufoff + VBUF_LEN) {
curp = bufp + (offset - bufoff);
return;
} else { /* not in current buffer, is it in any buffer? */
for (i = 0, vp = vbufd; i <= vlast; i++, vp++)
if (offset >= vp->bufoff && offset < vp->bufoff + VBUF_LEN) {
vswitch(i); /* switch to buffer with */
curp = bufp + (offset - bufoff); /* wanted offset */
return;
}
}
/* offset location isn't in memory, do it the old fashion way, read it */
readoff = offset & ~((long)(VBUF_LEN-1)); /* where to read from */
/* special case if seeking what would be the next or prev buffer, we
keep as much buffered in memory as possible */
if (labs(readoff - bufoff) == VBUF_LEN) { /* reading next or prev block? */
if (readoff > bufoff) { /* next block? */
pagefwd(fh,readoff); /* swap in next buffer */
vswitch(vidx+1); /* make it active */
} else { /* previous block */
pagebck(fh,readoff); /* swap in prev buffer */
vswitch(vidx-1); /* make it active */
}
} else { /* not reading next or prev buffer */
/* seeking to some random position in file, discard all current buffers
and start over from new position */
vidx = vlast = 0; /* discard all buffers */
vbufd[0].bufoff = bufoff = readoff; /* where to read from */
bufp = vbufd[0].bufp; /* where to read to */
l_seek(fh,readoff);
vbufd[0].buflen = buflen = readbuf(fh,bufp,VBUF_LEN);
endp = bufp + buflen;
}
curp = bufp + (offset - bufoff); /* got buffer, goto offset */
return;
}
/****************************************************************************
V N E X T C H
****************************************************************************/
int ALTCALL
vnextch(fh) /* return next character from file/buffers */
int fh;
{
/************** Following code is duplicated by some callers **************/
if (curp < endp) /* the normal case is just to return */
return(*curp++); /* the next character in the buffer */
/**************************************************************************/
if (buflen < VBUF_LEN) /* only last buffer can be < VBUF_LEN */
return(EOF);
if (vidx == vlast) /* read more from file? */
if (pagefwd(fh,bufoff+VBUF_LEN) == EOF) /* try paging into the file */
return(EOF); /* watch for EOF */
vswitch(vidx+1); /* switch to next buffer */
curp = bufp; /* at start of buffer */
return(*curp++); /* return 1st char in it */
}
/****************************************************************************
V P R E V C H
****************************************************************************/
int ALTCALL
vprevch(fh) /* return previous character from file/buffers */
int fh;
{
/************** Following code is duplicated by some callers **************/
if (curp > bufp) /* the normal case is just to return */
return(*--curp); /* the prev character in the buffer */
/**************************************************************************/
if (bufoff == 0) /* at top of file? (offset == 0) */
return(EOF);
if (vidx == 0) /* is this the oldest buffer? */
pagebck(fh,bufoff-VBUF_LEN); /* if so, page backward a buffer */
vswitch(vidx-1); /* switch to prev buffer */
curp = endp; /* at end of buffer */
return(*--curp); /* return last char in it */
}
/*****************************************************************************
P A G E F W D
*****************************************************************************/
static int ALTCALL
pagefwd(fh,offset) /* page forward into the file being read */
int fh;
long offset;
{
int i;
register VBUF_DES *vp;
char far *bp, far *malloc_f();
/* bump the index of the last buffer used, che